package com.guodi.model.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.guodi.common.utils.Asserts;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.boot.ctrl.BaseController;
import com.guodi.core.minio.util.MinioUtil;
import com.guodi.core.tool.api.R;
import com.guodi.core.tool.api.ResultCode;
import com.guodi.model.entity.UeProjectAttachment;
import com.guodi.model.service.IUeProjectAttachmentService;
import com.guodi.model.utils.FileUtil;
import com.guodi.model.utils.RecursionUtil;
import com.guodi.model.utils.ZipUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;


/**
 * @描述：项目管理-附件材料表控制类
 * @作者: 徐金洲
 * @日期: 2023-05-06
 */
@RestController
@RequestMapping("/UeProjectAttachment")
@Api(value = "API - UeProjectAttachmentController", tags = "附件材料表控制类")
public class UeProjectAttachmentController extends BaseController {

    @Value("${upload.tempFilePath}")
    private String tempFilePath;

    @Resource
    public IUeProjectAttachmentService ueProjectAttachmentService;


    /**
     * @描述: 根据父id查询附件材料树
     * @入参: parentId
     * @出参: tree
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/listTreeByParentId")
    @ApiOperation(value = " 根据父id查询附件材料树")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目id", required = true, dataType = "string", paramType = "query")
    })
    public R listTreeByParentId(String projectId) {
        //查询数据
        List<UeProjectAttachment> dataList = ueProjectAttachmentService.listTreeByParentId(projectId);
        //构建树结构
        List<UeProjectAttachment> buildtreelist = RecursionUtil.buildUeProjectAttachmentTree(dataList, "-1");
        return R.data(buildtreelist);
    }


    /**
     * @描述: 新增附件材料目录
     * @入参: UeProjectAttachment
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/saveDir")
    @ApiOperation(value = "新增附件材料目录")
    public R save(@Valid UeProjectAttachment ueProjectAttachment) {
        prepareData(ueProjectAttachment, true);
        ueProjectAttachment.setId(UuidUtil.get32UUID());
        ueProjectAttachmentService.save(ueProjectAttachment);
        return R.success("新增成功");
    }


    /**
     * @描述: 上传附件材料
     * @入参: projectId, parentId, files
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/uploadFile")
    @ApiOperation(value = "上传附件材料")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "parentId", value = "目录ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "files", value = "附件", required = true, dataType = "file", paramType = "query"),
    })
    public R<List<UeProjectAttachment>> uploadFile(String projectId, String parentId, MultipartFile[] files) {
        Asserts.isEmpty(projectId, "项目ID必传");
        Asserts.isEmpty(parentId, "目录ID");
        Asserts.isEmpty(files, "附件必传");
        if (org.apache.commons.lang.StringUtils.isBlank(parentId)) {
            parentId = "-1";
        }
        //上传附件
        try {
            ueProjectAttachmentService.uploadFile(projectId, parentId, files);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return R.success("上传附件成功");
        }
    }


    /**
     * @描述: 删除附件材料
     * @入参: projectId, id
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/delete")
    @ApiOperation(value = "删除附件")
    @ApiImplicitParam(name = "id", value = "Id", required = true, dataType = "string", paramType = "query")
    public R delete(String id) {
        Asserts.isEmpty(id, "删除ID必传");
        if (ueProjectAttachmentService.deleteById(id)) {
            return R.success("删除附件成功");
        } else {
            return R.fail("删除附件失败");
        }
    }


    /**
     * @描述: 删除目录(级联删除附件)
     * @入参: id
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/deleteDir")
    @ApiOperation(value = "删除目录(级联删除附件)")
    @ApiImplicitParam(name = "id", value = "Id", required = true, dataType = "string", paramType = "query")
    public R deleteDir(String id) {
        Asserts.isEmpty(id, "目录ID必传");
        //查询该目录下的附件信息
        LambdaQueryWrapper<UeProjectAttachment> queryWrapper = (new QueryWrapper()).lambda();
        queryWrapper.eq(UeProjectAttachment::getParentId, id);
        List<UeProjectAttachment> filelist = ueProjectAttachmentService.list(queryWrapper);
        //获取目录下附件的id,和文件路径,用于删除附件信息和文件
        boolean temp = true;
        for (UeProjectAttachment ua : filelist) {
            String ids = ua.getId();
            UeProjectAttachment file = ueProjectAttachmentService.getById(ids);
            //删除附件
            MinioUtil.removeFile(file.getFilePath());
            //删除附件信息
            temp = ueProjectAttachmentService.deleteByDirId(ids);
        }
        //删除目录信息
        boolean temp1 = ueProjectAttachmentService.deleteByDirId(id);
        if (temp && temp1) {
            return R.success("删除附件成功");
        } else {
            return R.fail("删除附件失败");
        }
    }


    /**
     * @描述: 下载附件材料
     * @入参: fileId
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/download")
    @ApiOperation(value = "下载附件")
    @ApiImplicitParam(name = "fileId", value = "附件ID", required = true, dataType = "string", paramType = "query")
    public R download(String fileId, HttpServletResponse response) throws IOException {
        Asserts.isEmpty(fileId, "删除ID必传");
        UeProjectAttachment file = ueProjectAttachmentService.getById(fileId);
        if (file == null) {
            return R.fail("附件数据不存在");
        }
        InputStream inputStream = MinioUtil.download(file.getFilePath());
        ServletOutputStream outputStream = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getFileName(), "UTF-8"));
            outputStream = response.getOutputStream();
            int len = 0;
            byte[] buf = new byte[10240];
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, len);
            }
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            outputStream.close();
        }
        return null;
    }


    /**
     * @描述: 下载附件材料压缩包
     * @入参: projectId
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/downloadZip")
    @ApiOperation(value = "下载附件材料压缩包")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "projectName", value = "项目名称", required = true, dataType = "string", paramType = "query")
    })
    public R downloadZip(String projectId, String projectName, HttpServletResponse response) throws IOException {
        Asserts.isEmpty(projectId, "项目id必传");
        Asserts.isEmpty(projectName, "项目名称必传");
        //根据项目id查询附件信息
        LambdaQueryWrapper<UeProjectAttachment> queryWrapper = (new QueryWrapper()).lambda();
        queryWrapper.eq(UeProjectAttachment::getProjectId, projectId);
        List<UeProjectAttachment> filelist = ueProjectAttachmentService.list(queryWrapper);
        //保存需要下载的附件id
        List<String> fileIdsList = new ArrayList<>();
        for (UeProjectAttachment ueProjectAttachment : filelist) {
            String parentId = ueProjectAttachment.getParentId();
            if (!parentId.equals("-1")) {
                String id = ueProjectAttachment.getId();
                fileIdsList.add(id);
            }
        }
        //保存附件的 url
        List<String> fileUrlList = new ArrayList<String>();
        //获取附件信息,校验是否存在
        UeProjectAttachment file = null;
        for (String id : fileIdsList) {
            file = ueProjectAttachmentService.getById(id);
            if (file == null) {
                return R.fail("附件数据不存在");
            } else {
                //保存附件材料路径 list
                String filePath = file.getFilePath();
                fileUrlList.add(filePath);
            }
        }
        //拼接zip名称
        String zipName = projectName;
        //批量次下载附件材料
        MinioUtil.batchDownload(fileUrlList, zipName, response);
        return null;
    }


    /**
     * @描述: 下载附件材料并进行压缩包导出(下载所有文件备选接口)
     * @入参: projectId
     * @出参:
     * @作者: 徐金洲
     * @日期: 2023-05-06
     **/
    @PostMapping("/downloadAll")
    @ApiOperation(value = "下载附件材料压缩包")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "projectName", value = "项目名称", required = true, dataType = "string", paramType = "query")
    })
    public R downloadAll(String projectId, String projectName, HttpServletResponse response) throws IOException {
        Asserts.isEmpty(projectId, "项目id必传");
        Asserts.isEmpty(projectName, "项目名称必传");
        //创建临时目录用于导出压缩包文件
        String tempDir = tempFilePath;
        File dir = new File(tempDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String msg = "";
        try{
            //根据项目id查询附件信息
            LambdaQueryWrapper<UeProjectAttachment> queryWrapper = (new QueryWrapper()).lambda();
            queryWrapper.eq(UeProjectAttachment::getProjectId, projectId);
            List<UeProjectAttachment> filelist = ueProjectAttachmentService.list(queryWrapper);
            //保存需要下载的附件id
            List<String> fileIdsList = new ArrayList<>();
            for (UeProjectAttachment ueProjectAttachment : filelist) {
                String parentId = ueProjectAttachment.getParentId();
                if (!parentId.equals("-1")) {
                    String id = ueProjectAttachment.getId();
                    fileIdsList.add(id);
                }
            }
            //校验是否存在附件
            for (String id : fileIdsList) {
                //获取附件信息,校验是否存在
                UeProjectAttachment ueProjectAttachment = ueProjectAttachmentService.getById(id);
                if (ueProjectAttachment == null) {
                    return R.fail("附件数据不存在");
                } else {
                    //获取附件材料路径 list
                    String filePath = ueProjectAttachment.getFilePath();
                    String fileName = ueProjectAttachment.getFileName();
                    //将文件下载下来,并存到临时目录
                    InputStream inputStream = MinioUtil.download(filePath);
                    File file = new File(tempDir + fileName);
                    //将inputStream 转成 file
                    FileUtil.copyInputStreamToFile(inputStream,file);
                }
            }
            //将目录下的文件进行压缩并下载
            msg = ZipUtil.zipDownload(tempDir, response);
        } catch (Exception e) {
            response.setContentType("text/html; charset=UTF-8"); //转码
            response.getWriter().println("文件下载失败！");
            e.printStackTrace();
            return R.fail(ResultCode.INTERNAL_SERVER_ERROR, e.getLocalizedMessage());
        } finally {
            //下载完成后删除文件夹,避免资源占用
            if (dir.exists()) {
                FileUtil.forceDeleteFile(dir);
            }
        }
        return R.success(msg);
    }


    private void prepareData(UeProjectAttachment ueProjectAttachment, boolean isSave) {
        if (isSave) {
            ueProjectAttachment.setCreator(this.getUser().getUserId().toString());
            ueProjectAttachment.setCreateTime(new Date());
            //防止误修改
            ueProjectAttachment.setModifier(null);
            ueProjectAttachment.setModifyTime(null);
        } else {
            ueProjectAttachment.setModifier(this.getUser().getUserId().toString());
            ueProjectAttachment.setModifyTime(new Date());
            //防止误修改
            ueProjectAttachment.setCreator(null);
            ueProjectAttachment.setCreateTime(null);
        }
    }


//    @PostMapping("/getMultipartFile")
//    @ApiOperation(value = "下载附件材料压缩包")
//    private R getMultipartFile(){
//
//        File file = new File("E:\\TEST\\test001.docx");
//
//        FileInputStream fileInputStream = null;
//        MultipartFile multipartFile = null;
//        try {
//            fileInputStream = new FileInputStream(file);
//            multipartFile = new MockMultipartFile(file.getName(),file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(),fileInputStream);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        System.out.println(multipartFile);
//        String filename = multipartFile.getOriginalFilename();
//        MinioUtil.uploadFile(multipartFile, filename);
//        return R.success("file 转 multipartFile 成功,并上传文件");
//    }


}
